pid = int(fd.readline())
os.kill(pid, signal.SIGTERM)
- """
- xc.domain_stop( dom=dom )
- XXX
- while not xc.domain_getinfo( first_dom=dom, max_doms=1 )[0]['stopped']:
- print "Sleep..."
- time.sleep(0.001);
- """
-
rc = xc.linux_save( dom=dom, state_file=file, progress=1)
- if rc == 0 : xc.domain_destroy( dom=dom, force=1 )
- else: xc.domain_start( dom=dom ) # sensible for production use
elif cmd == 'cpu_bvtslice':
if len(sys.argv) < 3:
out:
- if ( rc != 0 ) // destroy is something went wrong
+ if ( rc != 0 ) // destroy if something went wrong
{
if ( dom != 0 )
{
- op.cmd = DOM0_DESTROYDOMAIN;
- op.u.destroydomain.domain = (domid_t)dom;
- op.u.destroydomain.force = 1;
- (void)do_dom0_op(xc_handle, &op);
+ xc_domain_destroy( xc_handle, dom, 1 );
}
}
int verbose = flags & XCFLAGS_VERBOSE;
int live = flags & XCFLAGS_LIVE;
int debug = flags & XCFLAGS_DEBUG;
- int sent_last_iter, sent_this_iter, max_iters;
+ int sent_last_iter, sent_this_iter, skip_this_iter, max_iters;
/* Remember if we stopped the guest, so we can restart it on exit. */
int we_stopped_it = 0;
/* number of pages we're dealing with */
unsigned long nr_pfns;
- /* bitmap of pages left to send */
- unsigned long *to_send, *to_fix;
+ /* bitmap of pages:
+ - that should be sent this iteration (unless later marked as skip);
+ - to skip this iteration because already dirty;
+ - to fixup by sending at the end if not already resent; */
+ unsigned long *to_send, *to_skip, *to_fix;
int needed_to_fix = 0;
int total_sent = 0;
last_iter = 0;
sent_last_iter = 1<<20; // 4GB's worth of pages
- max_iters = 9; // limit us to 10 time round loop
+ max_iters = 19; // limit us to 20 times round loop
}
else
last_iter = 1;
to_send = malloc( sz );
to_fix = calloc( 1, sz );
+ to_skip = malloc( sz );
- if (!to_send || !to_fix)
+ if (!to_send || !to_fix || !to_skip)
{
ERROR("Couldn't allocate to_send array");
goto out;
}
+
memset( to_send, 0xff, sz );
if ( mlock( to_send, sz ) )
PERROR("Unable to mlock to_send");
return 1;
}
+
+ /* (to fix is local only) */
+
+ if ( mlock( to_skip, sz ) )
+ {
+ PERROR("Unable to mlock to_skip");
+ return 1;
+ }
+
}
iter++;
sent_this_iter = 0;
+ skip_this_iter = 0;
prev_pc = 0;
verbose_printf("Saving memory pages: iter %d 0%%", iter);
prev_pc = this_pc;
}
+ /* slightly wasteful to peek the whole array evey time,
+ but this is fast enough for the moment. */
+
+ if ( !last_iter &&
+ xc_shadow_control( xc_handle, domid,
+ DOM0_SHADOW_CONTROL_OP_PEEK,
+ to_skip, nr_pfns ) != nr_pfns )
+ {
+ ERROR("Error peeking shadow bitmap");
+ goto out;
+ }
+
/* load pfn_type[] with the mfn of all the pages we're doing in
this batch. */
test_bit(n,to_send),
live_mfn_to_pfn_table[live_pfn_to_mfn_table[n]&0xFFFFF]);
+ if (!last_iter && test_bit(n, to_send) && test_bit(n, to_skip))
+ skip_this_iter++; // stats keeping
+
+ if (! ( (test_bit(n, to_send) && !test_bit(n, to_skip)) ||
+ (test_bit(n, to_send) && last_iter) ||
+ (test_bit(n, to_fix) && last_iter) ) )
+ continue;
- if ( !test_bit(n, to_send ) &&
- !( last_iter && test_bit(n, to_fix ) ) ) continue;
+ /* we get here if:
+ 1. page is marked to_send & hasn't already been re-dirtied
+ 2. (ignore to_skip in last iteration)
+ 3. add in pages that still need fixup (net bufs)
+ */
pfn_batch[batch] = n;
pfn_type[batch] = live_pfn_to_mfn_table[n];
if( pfn_type[batch] == 0x80000004 )
{
+ /* not currently in pusedo-physical map -- set bit
+ in to_fix that we must send this page in last_iter
+ unless its sent sooner anyhow */
+
set_bit( n, to_fix );
if( iter>1 )
DDPRINTF("Urk! netbuf race: iter %d, pfn %lx. mfn %lx\n",
total_sent += sent_this_iter;
- verbose_printf("\b\b\b\b100%% (%d pages)\n", sent_this_iter );
+ verbose_printf("\b\b\b\b100%% (pages sent= %d, skipped= %d )\n",
+ sent_this_iter, skip_this_iter );
if ( last_iter )
{
if ( live )
{
if ( ( sent_this_iter > (sent_last_iter * 0.95) ) ||
- (iter >= max_iters) || (sent_this_iter < 10) )
+ (iter >= max_iters) || (sent_this_iter < 10) ||
+ (total_sent > nr_pfns*2) )
{
DPRINTF("Start last iteration\n");
last_iter = 1;
munmap(live_shinfo, PAGE_SIZE);
out:
- /* Restart the domain if we had to stop it to save its state. */
- if ( we_stopped_it )
- {
- printf("Restart domain\n");
- op.cmd = DOM0_STARTDOMAIN;
- op.u.startdomain.domain = (domid_t)domid;
- (void)do_dom0_op(xc_handle, &op);
- }
if ( pfn_type != NULL )
free(pfn_type);
struct hostent *h;
struct sockaddr_in s;
int sockbufsize;
+ int rc = -1;
int writerfn(void *fd, const void *buf, size_t count)
{
if ( xc_linux_save(xc->xc_handle, dom, flags,
writerfn, (void*)sd) == 0 )
{
- close(sd);
- Py_INCREF(zero);
- return zero;
+ if ( read( sd, &rc, sizeof(int) ) != sizeof(int) )
+ goto serr;
+
+ if ( rc == 0 )
+ {
+ printf("Migration succesful -- destroy local copy\n");
+ xc_domain_destroy( xc->xc_handle, dom, 1 );
+ close(sd);
+ Py_INCREF(zero);
+ return zero;
+ }
+ else
+ errno = rc;
}
serr:
+ printf("Migration failed -- restart local copy\n");
+ xc_domain_start( xc->xc_handle, dom );
PyErr_SetFromErrno(xc_error);
if ( sd >= 0 ) close(sd);
return NULL;
struct sockaddr_in s, d, p;
socklen_t dlen, plen;
int sockbufsize;
- int on = 1;
+ int on = 1, rc = -1;
int readerfn(void *fd, void *buf, size_t count)
{
sizeof sockbufsize) < 0 )
goto serr;
- if ( xc_linux_restore(xc->xc_handle, dom, flags,
- readerfn, (void*)sd, &dom) == 0 )
+ rc = xc_linux_restore(xc->xc_handle, dom, flags,
+ readerfn, (void*)sd, &dom);
+
+ write( sd, &rc, sizeof(int) );
+
+ if (rc == 0)
{
close(sd);
Py_INCREF(zero);
return zero;
}
+ errno = rc;
serr:
PyErr_SetFromErrno(xc_error);
}
static inline int shadow_page_op( struct mm_struct *m, unsigned int op,
- struct pfn_info *spfn_info )
+ struct pfn_info *spfn_info, int *work )
{
- int work = 0;
unsigned int spfn = spfn_info-frame_table;
+ int restart = 0;
switch( op )
{
{
if ( (spl1e[i] & _PAGE_PRESENT ) && (spl1e[i] & _PAGE_RW) )
{
- work++;
+ *work++;
spl1e[i] &= ~_PAGE_RW;
}
}
}
break;
+ case DOM0_SHADOW_CONTROL_OP_CLEAN2:
+ {
+ if ( (spfn_info->type_and_flags & PGT_type_mask) ==
+ PGT_l1_page_table )
+ {
+ delete_shadow_status( m, frame_table-spfn_info );
+ restart = 1; // we need to go to start of list again
+ }
+ else if ( (spfn_info->type_and_flags & PGT_type_mask) ==
+ PGT_l2_page_table )
+ {
+ unsigned long * spl1e = map_domain_mem( spfn<<PAGE_SHIFT );
+ memset( spl1e, 0, DOMAIN_ENTRIES_PER_L2_PAGETABLE * sizeof(*spl1e) );
+ unmap_domain_mem( spl1e );
+ }
+ else
+ BUG();
+ }
+ break;
+
+
+
}
- return work;
+ return restart;
}
static void __scan_shadow_table( struct mm_struct *m, unsigned int op )
{
int j, work=0;
- struct shadow_status *a;
+ struct shadow_status *a, *next;
// the code assumes you're not using the page tables i.e.
// the domain is stopped and cr3 is something else!!
for(j=0;j<shadow_ht_buckets;j++)
{
- a = &m->shadow_ht[j];
+ retry:
+ a = &m->shadow_ht[j];
+ next = a->next;
if (a->pfn)
{
- work += shadow_page_op( m, op, &frame_table[a->spfn_and_flags & PSH_pfn_mask] );
+ if ( shadow_page_op( m, op,
+ &frame_table[a->spfn_and_flags & PSH_pfn_mask],
+ &work ) )
+ goto retry;
}
- a=a->next;
+ a=next;
while(a)
{
- work += shadow_page_op( m, op, &frame_table[a->spfn_and_flags & PSH_pfn_mask] );
- a=a->next;
+ next = a->next;
+ if ( shadow_page_op( m, op,
+ &frame_table[a->spfn_and_flags & PSH_pfn_mask],
+ &work ) )
+ goto retry;
+ a=next;
}
shadow_audit(m,0);
}
__free_shadow_table( m );
break;
- case DOM0_SHADOW_CONTROL_OP_CLEAN:
+ case DOM0_SHADOW_CONTROL_OP_CLEAN: // zero all-non hypervisor
+ case DOM0_SHADOW_CONTROL_OP_CLEAN2: // zero all L2, free L1s
{
int i,j,zero=1;
if(p->mm.shadow_mode) shadow_mode_disable(p);
shadow_mode_enable(p, SHM_logdirty);
}
- else if ( p->mm.shadow_mode && cmd >= DOM0_SHADOW_CONTROL_OP_FLUSH && cmd<=DOM0_SHADOW_CONTROL_OP_PEEK )
+ else if ( p->mm.shadow_mode && cmd >= DOM0_SHADOW_CONTROL_OP_FLUSH && cmd<=DOM0_SHADOW_CONTROL_OP_CLEAN2 )
{
rc = shadow_mode_table_op(p, sc);
}
#define DOM0_SHADOW_CONTROL_OP_OFF 0
#define DOM0_SHADOW_CONTROL_OP_ENABLE_TEST 1
#define DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY 2
-#define DOM0_SHADOW_CONTROL_OP_FLUSH 10
+#define DOM0_SHADOW_CONTROL_OP_FLUSH 10 /* table ops */
#define DOM0_SHADOW_CONTROL_OP_CLEAN 11
#define DOM0_SHADOW_CONTROL_OP_PEEK 12
+#define DOM0_SHADOW_CONTROL_OP_CLEAN2 13
typedef struct dom0_shadow_control_st
{
/* IN variables. */